/**
 * @{#}VerifySignatureUtils.java Created on May 19, 2016 11:08:03 AM
 * <p>
 * Copyright (c) May 19, 2016 by ZHONGBO software.
 */
package com.fingard.dsp.bank.directbank.vbao03.trade.utils;

import com.vbao.service.trade.utils.XmlUtils;
import org.dom4j.DocumentException;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;

/**
 * @author 作者 E-mail:lirp@chinavbao.com 
 * @version 1.0
 * 类说明 
 */
public class VerifySignatureUtils {

    private static final List<String> not_sign_attrs = new ArrayList<String>();

    static {
        not_sign_attrs.add("Sign");
        not_sign_attrs.add("SignType");
        not_sign_attrs.add("BatchBankCode");
        not_sign_attrs.add("ResultCode");
        not_sign_attrs.add("ErrCode");
        not_sign_attrs.add("Description");
    }

    /**
     * returnOriDKPayxml 返回报文
     *
     * password 密钥
     *
     * InputCharset 字符编码
     */
    public boolean verifySignature(String returnOriDKPayxml, String password, String InputCharset) {
        SortedMap<String, String> value = new TreeMap<String, String>();
        try {
            value = XmlUtils.parseXML2(returnOriDKPayxml, null, value, true);
        } catch (DocumentException e) {
            e.printStackTrace();
        }

        String mySign = getStrMD(getSignContent(value) + password, InputCharset);

        if (null != value && value.get("ResultCode").length() > 0) {
            if (value.get("ResultCode").equals("F")) {
                return true;
            }
        }

        if (null != mySign && mySign.length() > 0 && null != value && value.get("Sign").length() > 0) {
            if (mySign.equals(value.get("Sign"))) {
                return true;
            }
        }
        return false;
    }


    private String getStrMD(String str, String InputCharset) {
        if (str == null)
            return null;
        byte[] inByte = null;
        try {
            inByte = str.getBytes(InputCharset);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        byte[] outByte = getMD(inByte);
        return byteToStr(outByte);
    }

    private byte[] getMD(byte[] inByte) {
        if (inByte == null) {
            return null;
        }
        byte[] hash = null;
        try {
            MessageDigest tMessageDigest = MessageDigest.getInstance("MD5");
            tMessageDigest.update(inByte);
            hash = tMessageDigest.digest();
        } catch (NoSuchAlgorithmException ex) {
            ex.printStackTrace();
        }
        return hash;
    }

    private String byteToStr(byte[] b) {
        if (b == null)
            return null;
        String hs = "";
        for (int n = 0; n < b.length; n++) {
            int v = b[n] & 0xFF;
            if (v < 16)
                hs = hs + "0";
            hs = hs + Integer.toString(v, 16).toUpperCase();
        }
        return hs;
    }

    private String getSignContent(SortedMap<String, ?> receiveData) {
        try {
            List<String> keys = getSortKey(receiveData);

            StringBuffer signContent = new StringBuffer("");

            for (String key : keys) {
                Object obj = receiveData.get(key);
                if (!(obj instanceof String)) {
                    continue;
                }
                String content = (String) obj;

                if ((content == null) || (content.length() <= 0)
                        || (not_sign_attrs.contains(key))
                        || content.equals("null") || ("").equals(content))
                    continue;
                if ((signContent != null) && (signContent.length() > 0)) {
                    signContent.append("&");
                }

                if ((content != null) && (content.trim().length() > 0)) {
                    signContent.append(key).append("=").append(content);
                }
            }
            return signContent.toString();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }

    private List<String> getSortKey(SortedMap<String, ?> receiveData) {
        List<String> attrs = new ArrayList<String>();
        for (String key : receiveData.keySet()) {
            attrs.add(key);
        }
        Arrays.sort(attrs.toArray(new Object[0]));
        return attrs;
    }

}
